﻿using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using ManagedUIFlow.Infrastructure.Commands;
using ManagedUIFlow.Properties;

namespace ManagedUIFlow.Model
{
    public class CommandBuilder {

        private Func<ICommandFactory> _factoryThunk;
        private static readonly CommandBuilder Instance = new CommandBuilder();
        private readonly HashSet<string> _namespaces = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

        public CommandBuilder()
        {
            SetCommandFactory(new DefaultCommandFactory()
                                  {
                                      CommandBuilder = this
                                  });
        }

        public static CommandBuilder Current {
            get {
                return Instance;
            }
        }

        public HashSet<string> DefaultNamespaces {
            get {
                return _namespaces;
            }
        }

        [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate",
            Justification = "Calling method multiple times might return different objects.")]
        public ICommandFactory GetCommandFactory() {
            var controllerFactoryInstance = _factoryThunk();
            return controllerFactoryInstance;
        }

        public void SetCommandFactory(ICommandFactory controllerFactory) {
            if (controllerFactory == null) {
                throw new ArgumentNullException("controllerFactory");
            }

            _factoryThunk = () => controllerFactory;
        }

        public void SetCommandFactory(Type commandFactoryType)
        {
            if (commandFactoryType == null)
            {
                throw new ArgumentNullException("commandFactoryType");
            }
            if (!typeof(ICommandFactory).IsAssignableFrom(commandFactoryType))
            {
                throw new ArgumentException(
                    String.Format(
                        CultureInfo.CurrentUICulture,
                        Resources.ControllerBuilder_MissingIControllerFactory,
                        commandFactoryType),
                    "commandFactoryType");
            }

            _factoryThunk = delegate() {
                                           try {
                                               return (ICommandFactory)Activator.CreateInstance(commandFactoryType);
                                           }
                                           catch (Exception ex) {
                                               throw new InvalidOperationException(
                                                   String.Format(
                                                       CultureInfo.CurrentUICulture,
                                                       Resources.ControllerBuilder_ErrorCreatingControllerFactory,
                                                       commandFactoryType),
                                                   ex);
                                           }
            };
        }
    }
}